package in.waffl.fairycake;

import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class Audio {
	private final InputStream file;
	private boolean stopped = true;
	public Audio(InputStream file) {
		this.file = file;
	}
	public void play() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				play(file);
			}
		}).start();
	}
	private void play(InputStream file) {
		stopped = false;
		try {
			AudioInputStream in = AudioSystem.getAudioInputStream(file);
			AudioInputStream din = null;
			if (in != null) {
				AudioFormat baseFormat = in.getFormat();
				AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
						baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2,
						baseFormat.getSampleRate(), false);
				din = AudioSystem.getAudioInputStream(decodedFormat, in);
				rawPlay(decodedFormat, din);
				in.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void rawPlay(AudioFormat targetFormat, AudioInputStream din) throws IOException, LineUnavailableException {
		byte[] data = new byte[4096];
		SourceDataLine line = getLine(targetFormat);
		if (line != null) {
			line.start();
			int nBytesRead = 0;
			while (nBytesRead != -1 && !stopped) {
				nBytesRead = din.read(data, 0, data.length);
				if (nBytesRead != -1) line.write(data, 0, nBytesRead);
			}
			line.drain();
			line.stop();
			line.close();
			din.close();
		}
	}

	private static SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException {
		SourceDataLine res = null;
		DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
		res = (SourceDataLine) AudioSystem.getLine(info);
		res.open(audioFormat);
		return res;
	}
	public void stop() {
		stopped = true;
	}
}
